package br.odb.bzk3.android.storytelling;

import java.util.HashMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import android.content.Context;
import android.content.res.XmlResourceParser;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Shader;
import android.util.Log;
import android.view.View;
import br.odb.bzk3.android.R;
import br.odb.bzk3.android.R.raw;
import br.odb.libscene.Color;
import br.odb.libsvg.ColoredPolygon;
import br.odb.libsvg.SVGUtils;
import br.odb.utils.math.Vec2;

public class StoryTellingView extends View {

	public class Gradient {
		public String id;
		public String link;
		GradientStop[] stops;
		public float x1;
		public float x2;
		public float y1;
		public float y2;

	}

	private class GradientStop {
		public int index;
		public String style;
	}

	HashMap<String, Gradient> gradients;
	Element root;
	XmlResourceParser xml;

	public StoryTellingView(Context context) {
		super(context);

		gradients = new HashMap<String, Gradient>();
		Log.d("bzk3", "vou começar a ler agora");
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

		try {
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document dom = builder.parse(getResources().openRawResource(
					R.raw.chapter4b ));
			root = dom.getDocumentElement();

		} catch (Exception e) {
			Log.d("bzk3", "deu merda mesmo");
		}
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		Paint paint = new Paint();
		paint.setColor(0xFF0000FF);
		paint.setStyle(Paint.Style.FILL_AND_STROKE);
		paint.setAntiAlias(true);

		String style = null;
		String d = null;
		Color color = null;

		// float x;
		// float y;
		// Path path = new Path();
		// x = 99.285714f;
		// y = 118.79075f;
		// path.moveTo( x, y );
		// x += 21.428576f;
		// y += 40.0f;
		// path.lineTo(x,y);
		// x += 152.14285f;
		// y += 6.42857f;
		// path.lineTo( x,y );
		// path.cubicTo(x -35.40483f,y-9.21169f, x-71.38344f,y-17.8496f,
		// x-86.39522f,y-47.45434f );
		// x+= -86.39522f;
		// y+= -47.45434f;
		// path.lineTo( x -87.176206f, y + 1.02577f );
		// path.close();
		// canvas.drawPath(path, paint);

		if (root != null) {

			NodeList paths = root.getElementsByTagName("*");

			for (int i = 0; i < paths.getLength(); i++) {

				Node item = paths.item(i);

				if (item.getNodeName().equalsIgnoreCase("linearGradient")) {

					NodeList nl = item.getChildNodes();
					Node stop;
					HashMap<Integer, GradientStop> stops = new HashMap<Integer, StoryTellingView.GradientStop>();
					NamedNodeMap data = item.getAttributes();

					Gradient g = new Gradient();
					g.id = data.getNamedItem("id").getNodeValue();

					if (data.getNamedItem("xlink:href") != null)
						// 0:#
						g.link = data.getNamedItem("xlink:href").getNodeValue()
								.substring(1);

					if (data.getNamedItem("x1") != null)
						g.x1 = Float.parseFloat(data.getNamedItem("x1")
								.getNodeValue());

					if (data.getNamedItem("y1") != null)
						g.y1 = Float.parseFloat(data.getNamedItem("y1")
								.getNodeValue());

					if (data.getNamedItem("x2") != null)
						g.x2 = Float.parseFloat(data.getNamedItem("x2")
								.getNodeValue());

					if (data.getNamedItem("y2") != null)
						g.y2 = Float.parseFloat(data.getNamedItem("y2")
								.getNodeValue());

					for (int c = 0; c < nl.getLength(); ++c) {

						stop = nl.item(c);
						if (stop.getNodeName().equalsIgnoreCase("stop")) {

							NamedNodeMap attr = stop.getAttributes();

							GradientStop gs = new GradientStop();
							attr.getNamedItem("id").getNodeValue();
							gs.index = Integer.parseInt(attr.getNamedItem(
									"offset").getNodeValue());
							gs.style = attr.getNamedItem("style")
									.getNodeValue();
							stops.put(Integer.valueOf(gs.index), gs);
						}
					}

					if (stops.size() > 0) {

						g.stops = new GradientStop[stops.size()];

						for (int c = 0; c < stops.size(); ++c) {

							g.stops[c] = stops.get(Integer.valueOf(c));
						}

						stops.clear();
					}

					gradients.put(g.id, g);
				}

				if (item.getNodeName().equalsIgnoreCase("rect")) {

					float x = 0;
					float y = 0;
					float width = 0;
					float height = 0;

					if (item.getAttributes().getNamedItem("x") != null)
						x = Float.parseFloat(item.getAttributes()
								.getNamedItem("x").getNodeValue());

					if (item.getAttributes().getNamedItem("y") != null)
						y = Float.parseFloat(item.getAttributes()
								.getNamedItem("y").getNodeValue());

					if (item.getAttributes().getNamedItem("width") != null)
						width = Float.parseFloat(item.getAttributes()
								.getNamedItem("width").getNodeValue());

					if (item.getAttributes().getNamedItem("height") != null)
						height = Float.parseFloat(item.getAttributes()
								.getNamedItem("height").getNodeValue());

					if (item.getAttributes().getNamedItem("style") != null)
						color = SVGUtils.parseColorFromStyle(item
								.getAttributes().getNamedItem("style")
								.getNodeValue());

					if (color != null)
						paint.setColor((int) color.getARGBColor());
					else
						paint.setColor(0xFF000000);

					Rect r = new Rect();
					r.top = (int) y;
					r.bottom = (int) (y + height);
					r.right = (int) (x + width);
					r.left = (int) x;

					canvas.drawRect(r, paint);

				} else if (item.getNodeName().equalsIgnoreCase("path")) {

					NamedNodeMap properties = item.getAttributes();

					for (int j = 0; j < properties.getLength(); j++) {
						Node property = properties.item(j);
						String name = property.getNodeName();
						Log.d("bzk3", "::" + name);
						if (name.equalsIgnoreCase("d")) {
							d = property.getNodeValue();
						}

						if (name.equalsIgnoreCase("style")) {
							style = property.getNodeValue();
						}
					}
				}

				if (d != null)
					parsePath(canvas, paint, d, style);
			}
		}
	}

	private void parsePath(Canvas canvas, Paint paint, String nodeValue,
			String style) {
		
		float scale;
		
		if ( getHeight() < getWidth() )
			scale = getHeight() / 480.0f;
		else
			scale = getWidth() / 800.0f;
		

		ColoredPolygon pol = SVGUtils
				.parseD(nodeValue, getWidth(), getHeight());
		pol.color = SVGUtils.parseColorFromStyle(style);
		String gradient = null;

		if (pol.color == null)
			gradient = SVGUtils.parseGradientFromStyle(style);

		Path path = new Path();
		path.moveTo( pol.xpoints[0] * scale, pol.ypoints[0] * scale );

		for (int c = 0; c < pol.npoints; ++c) {
			if (((Vec2) pol.controlPoints.get(c)).isValid()) {
				Vec2 control = (Vec2) pol.controlPoints.get(c);
				path.cubicTo(pol.xpoints[c] * scale, pol.ypoints[c] * scale, control.getX() * scale,
						control.getY() * scale, pol.xpoints[c + 1] * scale, pol.ypoints[c + 1] * scale );
				++c;
			} else
				path.lineTo(pol.xpoints[c] * scale, pol.ypoints[c] * scale );
		}

		path.close();
		paint.setShader(null);
		paint.setAlpha(255);

		if (gradient != null) {

			Gradient g0 = gradients.get(gradient);
			Gradient g1 = null;

			if (g0.stops == null && g0.link != null) {
				g1 = gradients.get(g0.link);
			} else {
				g1 = g0;
			}

			LinearGradient lg = new LinearGradient(g0.x1, g0.y1, g0.x2, g0.y2,
					(int) SVGUtils.parseColorFromStyle(g1.stops[0].style,
							"stop-color", "stop-opacity").getARGBColor(),
					(int) SVGUtils.parseColorFromStyle(g1.stops[1].style,
							"stop-color", "stop-opacity").getARGBColor(),
					Shader.TileMode.MIRROR);

			paint.setShader(lg);

		} else if (pol.color != null)
			paint.setColor((int) pol.color.getARGBColor());
		else
			paint.setColor(0xFF000000);

		canvas.drawPath(path, paint);
	}
}
